package com.fessc.develop.handler.processor.request;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.fessc.develop.base.Result;
import com.fessc.develop.entity.comvo.*;
import com.fessc.develop.entity.dbvo.TAccountSynchron;
import com.fessc.develop.entity.ccbvo.CCBResponseBodyVo;
import com.fessc.develop.entity.dbvo.TOrgUrlManage;
import com.fessc.develop.handler.SignHandler;
import com.fessc.develop.model.enums.*;
import com.fessc.develop.service.impl.TAccountSynchronServiceImpl;
import com.fessc.develop.service.impl.TOrgUrlManageServiceImpl;
import com.fessc.develop.utils.*;
import lombok.extern.slf4j.Slf4j;
import org.slf4j.MDC;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.Map;

@Slf4j
@Service
public class ComAccountSyncService implements IBaseService {

    @Resource
    private SignHandler signHandler;

    @Resource
    private TOrgUrlManageServiceImpl tOrgUrlManageService;

    @Resource
    private TAccountSynchronServiceImpl accountSynchronServiceImpl;

    @Resource
    private OkHttpUtil okHttpUtil;

    @Override
    public String getServiceCode() {
        return EnumServiceCode.COM_BS0004.toString();
    }

    @Override
    public Result process(JSONObject request) {
        log.info("银行账户信息同步请求报文: " + request.toJSONString());
        AccountSynchronVo accountSynchronReqVo = JSON.parseObject(request.getJSONObject(EnumJsonProperty.REQ_BODY.toString()).toJSONString(), AccountSynchronVo.class);
        SysHeadVo sysHeadVo = JSON.parseObject(request.getJSONObject(EnumJsonProperty.REQ_SYS_HEAD.toString()).toJSONString(), SysHeadVo.class);

        Result result = new Result();
        String errorCode = "";

        // 检查请求报文各个字段内容是否符合要求
        if (BusiUtil.isNotEquals(accountSynchronReqVo.getCumTp(), "1") && BusiUtil.isNotEquals(accountSynchronReqVo.getCumTp(), "2")
                && BusiUtil.isNotEquals(accountSynchronReqVo.getCumTp(), "3") && BusiUtil.isNotEquals(accountSynchronReqVo.getCumTp(), "4")) {
            errorCode = "EE1007";
        } else if (!BusiUtil.isNotNullAll(accountSynchronReqVo.getNat(),
                accountSynchronReqVo.getName(), accountSynchronReqVo.getCrdtNo(), accountSynchronReqVo.getCrdtTp())) {
            errorCode = "EE1029";
        } else if (!BusiUtil.isNotNullAll(accountSynchronReqVo.getBnkCd(),
                accountSynchronReqVo.getBnkName())) {
            errorCode = "EE1030";
        } else if (!BusiUtil.isNotNullAll(accountSynchronReqVo.getAccNo(),
                accountSynchronReqVo.getAccName(), accountSynchronReqVo.getAccSts())) {
            errorCode = "EE1031";
        }

        // 返回错误信息
        if (BusiUtil.isNotNull(errorCode)) {
            result = new Result(EnumResultType.SUCCESS.getStatusCode(), EnumResultType.SUCCESS.getMsg());
            JSONObject jsonObject = new JSONObject();
            jsonObject.put("PcsgRlt", "01");
            jsonObject.put("FalRs", ErrorUtil.getErrorDesc(errorCode));
            result.setData(jsonObject);
            return result;
        }

        switch (accountSynchronReqVo.getCumTp()) {
            case "1":
                //todo:同步边民开户信息至市场交易平
                result = accountSynchron(accountSynchronReqVo, sysHeadVo);
                break;
            case "2":
                //todo:同步边民代表开户信息至市场交易平
                result = accountSynchron(accountSynchronReqVo, sysHeadVo);
                break;
            case "3":
                //todo:同步委托付汇代理人开户信息至市场交易平
                result = accountSynchron(accountSynchronReqVo, sysHeadVo);
                break;
            case "4":
                //todo:同步商铺开户信息至市场交易平
                result = accountSynchron(accountSynchronReqVo, sysHeadVo);
                break;
            default:
                //todo:报错
                throw ExceptionUtil.businessException("EE4013");
        }
        log.info("银行账户信息同步返回报文: " + JSON.toJSONString(result));
        return result;
    }

    /**
     * 银行同步边民商铺开户信息至市场交易平台
     */
    private Result accountSynchron(AccountSynchronVo accountSynchronReqVo, SysHeadVo sysHeadVo) {
        //组装发送公共交易中心报文
        CommonSendVo<Object> commonSendVo = new CommonSendVo<>();
        sysHeadVo.setServiceCode(EnumServiceCode.PLAT_MP0002.toString());
        CommonHeadSendVo commonHeadSendVo = new CommonHeadSendVo();
        BeanUtils.copyProperties(sysHeadVo, commonHeadSendVo);
        commonSendVo.setCommonHeadSendVo(commonHeadSendVo);
        commonSendVo.setBody(accountSynchronReqVo);
        log.info("互联互通转发账户信息同步请求明文: " + JSON.toJSONString(commonSendVo));

        //根据机构查询配置表获取URL，通用默认一个机构只有一个URL
        TOrgUrlManage orgUrlManage = tOrgUrlManageService.getOrgUrlByOrgCodeAndKey(sysHeadVo.getOrgCode(), EnumOrgType.OTHER.toString(), EnumServiceCode.PLAT_MP0002.toString());
        String afterEncrypt = signHandler.encrypt(JSON.toJSONString(accountSynchronReqVo), orgUrlManage.getPubCert());
        commonSendVo.setBody(afterEncrypt);
        Map<String, String> requestHeaders = okHttpUtil.getRequestHeaders(orgUrlManage.getAppKey(), orgUrlManage.getInterfaceUrl(), commonHeadSendVo.getBankId());
        log.info("互联互通转发账户信息同步请求密文：" + JSON.toJSONString(commonSendVo));

        //接口推送
        String responseEncryptJson = "";  //返回加密报文
        JSONObject responseDecryptJson = new JSONObject();  //解密后报文
        try {
            // 先解析返回报文
            responseEncryptJson = okHttpUtil.doPostJson(orgUrlManage.getInterfaceUrl(), JSON.toJSONString(commonSendVo), requestHeaders);
            responseDecryptJson = JSON.parseObject(responseEncryptJson);
            log.info("银行账号信息同步响应报文(解密前): " + JSON.toJSONString(responseDecryptJson));
            String date = responseDecryptJson.getString(EnumJsonProperty.RES_DATA.toString());
            // 解密DATA部分
            if (BusiUtil.isNotNull(date)) {
                responseDecryptJson.put(EnumJsonProperty.RES_DATA.toString(), JSONObject.parseObject(signHandler.decrypt(date)));
            }
            log.info("银行账号信息同步响应报文(解密后): " + JSON.toJSONString(responseDecryptJson));
        } catch (Exception e) {
            log.info("银行账号信息同步响应报文解析失败: " + e.getMessage());
        }

        // 返回报文
        Result result = new Result(responseDecryptJson.getString(EnumJsonProperty.RES_STATUS_CODE.toString()), responseDecryptJson.getString(EnumJsonProperty.RES_STATUS_MSG.toString()));
        JSONObject resDate = responseDecryptJson.getJSONObject(EnumJsonProperty.RES_DATA.toString());
        CCBResponseBodyVo bodyVo = JSON.parseObject(JSON.toJSONString(resDate), CCBResponseBodyVo.class);
        result.setData(bodyVo);

        //保存银行反馈边民商铺开户信息
        try {
            log.info("保存银行账号同步信息：" + accountSynchronReqVo.getName() + "，" + accountSynchronReqVo.getAccNo());
            TAccountSynchron accountSynchron = getTAccountSynchron(accountSynchronReqVo, sysHeadVo, bodyVo);
            accountSynchronServiceImpl.save(accountSynchron);
        } catch (Exception e) {
            log.info("保存银行账号同步信息失败: " + e.getMessage());
        }
        return result;
    }

    private static TAccountSynchron getTAccountSynchron(AccountSynchronVo accountSynchronReqVo, SysHeadVo sysHeadVo, CCBResponseBodyVo bodyVo) {
        TAccountSynchron accountSynchron = new TAccountSynchron();
        accountSynchron.setLogId(MDC.get("lodId"));
        accountSynchron.setBankId(sysHeadVo.getBankId());
        accountSynchron.setOrgCode(sysHeadVo.getOrgCode());
        accountSynchron.setSignType(accountSynchronReqVo.getCumTp());
        accountSynchron.setName(accountSynchronReqVo.getName());
        accountSynchron.setCardType(accountSynchronReqVo.getCrdtTp());
        accountSynchron.setCardNo(accountSynchronReqVo.getCrdtNo());
        accountSynchron.setNat(accountSynchronReqVo.getNat());
        accountSynchron.setAccountNo(accountSynchronReqVo.getAccNo());
        accountSynchron.setBankCode(accountSynchronReqVo.getBnkCd());
        accountSynchron.setTel(accountSynchronReqVo.getTel());
        accountSynchron.setOvseaInd(accountSynchronReqVo.getOvseaInd());
        accountSynchron.setSignInd(accountSynchronReqVo.getIsNRA());
        accountSynchron.setRequestTime(DateUtil.getCurrentLocalDateTime());
        accountSynchron.setOrgCode(sysHeadVo.getOrgCode());
        accountSynchron.setResponseCode(bodyVo.getPsgrlt());
        accountSynchron.setResponseLog(bodyVo.getFalrs());
        return accountSynchron;
    }
}
